package com.gitee.cnlongdb.server.connect;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import com.gitee.cnlongdb.basic.config.LongDbConfig;
import com.gitee.cnlongdb.basic.constant.LongDbConstant;
import com.gitee.cnlongdb.basic.entity.matchingrule.MatchingDataTime;
import com.gitee.cnlongdb.basic.utils.NumberHandlerUtils;
import com.gitee.cnlongdb.server.connect.nettymission.LongdbNettyServer;
import com.gitee.cnlongdb.server.connect.nettymission.operator.NettyDataOperator;
import com.gitee.cnlongdb.server.operator.create.CreateOperator;
import com.gitee.cnlongdb.server.operator.insert.InsertOperator;
import com.gitee.cnlongdb.server.operator.query.QueryOperator;
import com.gitee.cnlongdb.server.operator.remove.RemoveOperator;
import com.gitee.cnlongdb.server.operator.update.UpdateOperator;

/**
 * 系统名称：LongDbConnect.java
 * 模块名称：
 * 模块描述：longdb - 数据库连接对象
 * 功能列表：
 * 模块作者：ZOUYONG
 * 开发时间：2018年12月5日 下午9:55:11
 * 模块路径：com.gitee.cnlongdb.server.connect.LongDbConnect
 * 更新记录：
 */
public class LongDbConnect implements Serializable {

	// 序列化ID
	private static final long serialVersionUID = 1L;

	// 数据库根目录
	private String dataBaseRootDirectory;
	
	// 数据库名称
	private String dataBaseName;
	
	// 数据库ip
	private String dataBaseIp;
	
	// 数据库端口，初始化带有默认端口：52168
	private int dataBasePort = LongDbConfig.longdbDefaultPort;
	
	// 数据库全局配置信息
	private List<Object> matchingList = new ArrayList<Object>();
	
	// 创建执行器
	private CreateOperator createOperator;
	
	// 新增执行器
	private InsertOperator insertOperator;
	
	// 删除执行器
	private RemoveOperator removeOperator;
	
	// 修改执行器
	private UpdateOperator updateOperator;
	
	// 查询执行器
	private QueryOperator queryOperator;
	
	/**
	 * 构建[中国龙cnlongdb]数据库连接对象
	 * @param dataBaseRootDirectory
	 * @param dataBaseName
	 * @param dataBaseIp
	 * @param dataBasePort
	 */
	public LongDbConnect(String dataBaseRootDirectory, String dataBaseName, String dataBaseIp, int dataBasePort) {
		// 校验数据库连接参数的正确性
		checkConnectData(dataBaseRootDirectory, dataBaseName, dataBaseIp, dataBasePort);
		this.dataBaseRootDirectory = dataBaseRootDirectory;
		this.dataBaseName = dataBaseName;
		this.dataBaseIp = dataBaseIp;
		this.dataBasePort = dataBasePort;
		// 实例化各种执行器
		initOperatorActuator();
		// 初始化数据库信息
		initDataBaseInfo();
		// 开启各种监听
		startOperatorMonitor();
	}

	/**
	 * 功能描述：初始化数据库信息
	 × 模块作者：ZOUYONG
	 × 开发时间：2018年12月25日 上午10:17:32
	 × 返回数据：void
	 */
	private void initDataBaseInfo() {
		this.createOperator.createDataBase(dataBaseName);
	}

	/**
	 * 功能描述：实例化执行器
	 * 模块作者：ZOUYONG
	 * 开发时间：2018年12月7日 下午9:22:51
	 * 更新记录：
	 * 返回数据：void
	 */
	private void initOperatorActuator() {
		// 新增执行器
		insertOperator = new InsertOperator(this);
		// 创建执行器
		createOperator = new CreateOperator(this);
		// 查询执行器
		queryOperator = new QueryOperator(this);
		// 修改执行器
		updateOperator = new UpdateOperator(this);
		// 删除执行器
		removeOperator = new RemoveOperator(this);
	}

	/**
	 * 功能描述：开启各种监听
	 × 模块作者：ZOUYONG
	 × 开发时间：2018年12月21日 下午4:52:31
	 × 返回数据：void
	 */
	private void startOperatorMonitor() {
		// 开启netty网络监听
		new LongdbNettyServer(this, new NettyDataOperator(this)).start();
	}

	/**
	 * 功能描述：校验数据库连接参数的正确性
	 × 模块作者：ZOUYONG
	 × 开发时间：2018年12月7日 下午4:21:37
	 × 返回数据：void
	 */
	public static void checkConnectData(String dataBaseRootDirectory, String dataBaseName, String dataBaseIp, int dataBasePort) {
		if(StringUtils.isBlank(dataBaseRootDirectory) || !new File(dataBaseRootDirectory).exists()) {
			throw new RuntimeException(LongDbConstant.longdbDefaultName + "数据库[DataBaseRootDirectory]根目录不存在！");
		}
		if(StringUtils.isBlank(dataBaseName)) {
			throw new RuntimeException(LongDbConstant.longdbDefaultName + "数据库名称不能为空！");
		}
		if(StringUtils.isBlank(dataBaseIp) || !NumberHandlerUtils.isIpStr(dataBaseIp)) {
			throw new RuntimeException(LongDbConstant.longdbDefaultName + "数据库IP格式有误！");
		}
		if(dataBasePort <= 0) {
			throw new RuntimeException(LongDbConstant.longdbDefaultName + "数据库端口必须大于0！");
		}
	}
	
	/**
	 * 功能描述：设置时间分区规则
	 × 模块作者：ZOUYONG
	 × 开发时间：2019年4月15日 下午4:17:21
	 × 返回数据：void
	 */
	public void setDateTimeMatching(String relationName, String timePartition, boolean isBaseData) {
		MatchingDataTime dataTime = new MatchingDataTime();
		if(isBaseData) {
			dataTime.setRelationDataBase(relationName);
		} else {
			dataTime.setRelationTableName(relationName);
		}
		dataTime.setTimePartition(timePartition);
		this.matchingList.add(dataTime);
	}

	public String getDataBaseRootDirectory() {
		return dataBaseRootDirectory;
	}

	public void setDataBaseRootDirectory(String dataBaseRootDirectory) {
		this.dataBaseRootDirectory = dataBaseRootDirectory;
	}

	public String getDataBaseName() {
		return dataBaseName;
	}

	public void setDataBaseName(String dataBaseName) {
		this.dataBaseName = dataBaseName;
	}

	public String getDataBaseIp() {
		return dataBaseIp;
	}

	public void setDataBaseIp(String dataBaseIp) {
		this.dataBaseIp = dataBaseIp;
	}

	public int getDataBasePort() {
		return dataBasePort;
	}

	public void setDataBasePort(int dataBasePort) {
		this.dataBasePort = dataBasePort;
	}

	public List<Object> getMatchingList() {
		return matchingList;
	}

	public void setMatchingList(List<Object> matchingList) {
		this.matchingList = matchingList;
	}

	public CreateOperator getCreateOperator() {
		return createOperator;
	}

	public void setCreateOperator(CreateOperator createOperator) {
		this.createOperator = createOperator;
	}

	public InsertOperator getInsertOperator() {
		return insertOperator;
	}

	public void setInsertOperator(InsertOperator insertOperator) {
		this.insertOperator = insertOperator;
	}

	public RemoveOperator getRemoveOperator() {
		return removeOperator;
	}

	public void setRemoveOperator(RemoveOperator removeOperator) {
		this.removeOperator = removeOperator;
	}

	public UpdateOperator getUpdateOperator() {
		return updateOperator;
	}

	public void setUpdateOperator(UpdateOperator updateOperator) {
		this.updateOperator = updateOperator;
	}

	public QueryOperator getQueryOperator() {
		return queryOperator;
	}

	public void setQueryOperator(QueryOperator queryOperator) {
		this.queryOperator = queryOperator;
	}

}
